// Licensed to Elasticsearch B.V under one or more agreements.
// Elasticsearch B.V licenses this file to you under the Apache 2.0 License.
// See the LICENSE file in the project root for more information.
//
// ███╗   ██╗ ██████╗ ████████╗██╗ ██████╗███████╗
// ████╗  ██║██╔═══██╗╚══██╔══╝██║██╔════╝██╔════╝
// ██╔██╗ ██║██║   ██║   ██║   ██║██║     █████╗
// ██║╚██╗██║██║   ██║   ██║   ██║██║     ██╔══╝
// ██║ ╚████║╚██████╔╝   ██║   ██║╚██████╗███████╗
// ╚═╝  ╚═══╝ ╚═════╝    ╚═╝   ╚═╝ ╚═════╝╚══════╝
// ------------------------------------------------
//
// This file is automatically generated.
// Please do not edit these files manually.
//
// ------------------------------------------------

#nullable restore

using System;
using System.Linq;
using Elastic.Clients.Elasticsearch.Serialization;

namespace Elastic.Clients.Elasticsearch;

/// <summary>
/// <para>
/// A geo bounding box. It can be represented in various ways:
/// </para>
/// <list type="bullet">
/// <item>
/// <para>
/// as 4 top/bottom/left/right coordinates
/// </para>
/// </item>
/// <item>
/// <para>
/// as 2 top_left / bottom_right points
/// </para>
/// </item>
/// <item>
/// <para>
/// as 2 top_right / bottom_left points
/// </para>
/// </item>
/// <item>
/// <para>
/// as a WKT bounding box
/// </para>
/// </item>
/// </list>
/// </summary>
public sealed partial class GeoBounds : Elastic.Clients.Elasticsearch.Core.IComplexUnion<Elastic.Clients.Elasticsearch.GeoBounds.Kind>
{
	public enum Kind
	{
		Coordinates,
		TopLeftBottomRight,
		TopRightBottomLeft,
		Wkt
	}

	private readonly Kind _kind;
	private readonly object _value;

	Kind Elastic.Clients.Elasticsearch.Core.IComplexUnion<Kind>.ValueKind => _kind;

	object Elastic.Clients.Elasticsearch.Core.IComplexUnion<Kind>.Value => _value;

	private GeoBounds(Kind kind, object value)
	{
		_kind = kind;
		_value = value;
	}

	internal GeoBounds(Elastic.Clients.Elasticsearch.CoordsGeoBounds variant) : this(Kind.Coordinates, variant)
	{
	}

	public static Elastic.Clients.Elasticsearch.GeoBounds Coordinates(Elastic.Clients.Elasticsearch.CoordsGeoBounds coordinates) => new(Kind.Coordinates, coordinates);

	public bool IsCoordinates => _kind is Kind.Coordinates;

	public bool TryGetCoordinates([System.Diagnostics.CodeAnalysis.NotNullWhen(true)] out Elastic.Clients.Elasticsearch.CoordsGeoBounds? coordinates)
	{
		coordinates = null;
		if (_kind == Kind.Coordinates)
		{
			coordinates = (Elastic.Clients.Elasticsearch.CoordsGeoBounds)_value;
			return true;
		}

		return false;
	}

	public static implicit operator Elastic.Clients.Elasticsearch.GeoBounds(Elastic.Clients.Elasticsearch.CoordsGeoBounds coordinates) => GeoBounds.Coordinates(coordinates);

	internal GeoBounds(Elastic.Clients.Elasticsearch.TopLeftBottomRightGeoBounds variant) : this(Kind.TopLeftBottomRight, variant)
	{
	}

	public static Elastic.Clients.Elasticsearch.GeoBounds TopLeftBottomRight(Elastic.Clients.Elasticsearch.TopLeftBottomRightGeoBounds topLeftBottomRight) => new(Kind.TopLeftBottomRight, topLeftBottomRight);

	public bool IsTopLeftBottomRight => _kind is Kind.TopLeftBottomRight;

	public bool TryGetTopLeftBottomRight([System.Diagnostics.CodeAnalysis.NotNullWhen(true)] out Elastic.Clients.Elasticsearch.TopLeftBottomRightGeoBounds? topLeftBottomRight)
	{
		topLeftBottomRight = null;
		if (_kind == Kind.TopLeftBottomRight)
		{
			topLeftBottomRight = (Elastic.Clients.Elasticsearch.TopLeftBottomRightGeoBounds)_value;
			return true;
		}

		return false;
	}

	public static implicit operator Elastic.Clients.Elasticsearch.GeoBounds(Elastic.Clients.Elasticsearch.TopLeftBottomRightGeoBounds topLeftBottomRight) => GeoBounds.TopLeftBottomRight(topLeftBottomRight);

	internal GeoBounds(Elastic.Clients.Elasticsearch.TopRightBottomLeftGeoBounds variant) : this(Kind.TopRightBottomLeft, variant)
	{
	}

	public static Elastic.Clients.Elasticsearch.GeoBounds TopRightBottomLeft(Elastic.Clients.Elasticsearch.TopRightBottomLeftGeoBounds topRightBottomLeft) => new(Kind.TopRightBottomLeft, topRightBottomLeft);

	public bool IsTopRightBottomLeft => _kind is Kind.TopRightBottomLeft;

	public bool TryGetTopRightBottomLeft([System.Diagnostics.CodeAnalysis.NotNullWhen(true)] out Elastic.Clients.Elasticsearch.TopRightBottomLeftGeoBounds? topRightBottomLeft)
	{
		topRightBottomLeft = null;
		if (_kind == Kind.TopRightBottomLeft)
		{
			topRightBottomLeft = (Elastic.Clients.Elasticsearch.TopRightBottomLeftGeoBounds)_value;
			return true;
		}

		return false;
	}

	public static implicit operator Elastic.Clients.Elasticsearch.GeoBounds(Elastic.Clients.Elasticsearch.TopRightBottomLeftGeoBounds topRightBottomLeft) => GeoBounds.TopRightBottomLeft(topRightBottomLeft);

	internal GeoBounds(Elastic.Clients.Elasticsearch.WktGeoBounds variant) : this(Kind.Wkt, variant)
	{
	}

	public static Elastic.Clients.Elasticsearch.GeoBounds Wkt(Elastic.Clients.Elasticsearch.WktGeoBounds wkt) => new(Kind.Wkt, wkt);

	public bool IsWkt => _kind is Kind.Wkt;

	public bool TryGetWkt([System.Diagnostics.CodeAnalysis.NotNullWhen(true)] out Elastic.Clients.Elasticsearch.WktGeoBounds? wkt)
	{
		wkt = null;
		if (_kind == Kind.Wkt)
		{
			wkt = (Elastic.Clients.Elasticsearch.WktGeoBounds)_value;
			return true;
		}

		return false;
	}

	public static implicit operator Elastic.Clients.Elasticsearch.GeoBounds(Elastic.Clients.Elasticsearch.WktGeoBounds wkt) => GeoBounds.Wkt(wkt);
}

public readonly partial struct GeoBoundsFactory
{
	public Elastic.Clients.Elasticsearch.GeoBounds Coordinates(Elastic.Clients.Elasticsearch.CoordsGeoBounds value)
	{
		return new Elastic.Clients.Elasticsearch.GeoBounds(value);
	}

	public Elastic.Clients.Elasticsearch.GeoBounds Coordinates(System.Action<Elastic.Clients.Elasticsearch.CoordsGeoBoundsDescriptor> action)
	{
		return new Elastic.Clients.Elasticsearch.GeoBounds(Elastic.Clients.Elasticsearch.CoordsGeoBoundsDescriptor.Build(action));
	}

	public Elastic.Clients.Elasticsearch.GeoBounds TopLeftBottomRight(Elastic.Clients.Elasticsearch.TopLeftBottomRightGeoBounds value)
	{
		return new Elastic.Clients.Elasticsearch.GeoBounds(value);
	}

	public Elastic.Clients.Elasticsearch.GeoBounds TopLeftBottomRight(System.Action<Elastic.Clients.Elasticsearch.TopLeftBottomRightGeoBoundsDescriptor> action)
	{
		return new Elastic.Clients.Elasticsearch.GeoBounds(Elastic.Clients.Elasticsearch.TopLeftBottomRightGeoBoundsDescriptor.Build(action));
	}

	public Elastic.Clients.Elasticsearch.GeoBounds TopRightBottomLeft(Elastic.Clients.Elasticsearch.TopRightBottomLeftGeoBounds value)
	{
		return new Elastic.Clients.Elasticsearch.GeoBounds(value);
	}

	public Elastic.Clients.Elasticsearch.GeoBounds TopRightBottomLeft(System.Action<Elastic.Clients.Elasticsearch.TopRightBottomLeftGeoBoundsDescriptor> action)
	{
		return new Elastic.Clients.Elasticsearch.GeoBounds(Elastic.Clients.Elasticsearch.TopRightBottomLeftGeoBoundsDescriptor.Build(action));
	}

	public Elastic.Clients.Elasticsearch.GeoBounds Wkt(Elastic.Clients.Elasticsearch.WktGeoBounds value)
	{
		return new Elastic.Clients.Elasticsearch.GeoBounds(value);
	}

	public Elastic.Clients.Elasticsearch.GeoBounds Wkt(System.Action<Elastic.Clients.Elasticsearch.WktGeoBoundsDescriptor> action)
	{
		return new Elastic.Clients.Elasticsearch.GeoBounds(Elastic.Clients.Elasticsearch.WktGeoBoundsDescriptor.Build(action));
	}

	[System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
	internal static Elastic.Clients.Elasticsearch.GeoBounds Build(System.Func<Elastic.Clients.Elasticsearch.GeoBoundsFactory, Elastic.Clients.Elasticsearch.GeoBounds> action)
	{
		var builder = new Elastic.Clients.Elasticsearch.GeoBoundsFactory();
		return action.Invoke(builder);
	}
}